import { All, Controller, Get, Req, Res, UseGuards } from "@nestjs/common";
import { GatewayService } from "./gateway.service";
import { MessagePattern } from "@nestjs/microservices";
import { SysIntervalMsgType } from "../../../types/types";
import { WsGateway } from "./ws/ws.gateway";
import { configuration, RBAC } from "../../../config/config";
import { PrismaService } from "@app/prisma";
import { NoNeedLogin } from "../../../libs/decorator/no-need-login/no-need-login.decorator";
import { LogService } from "@app/log";
import { createProxyMiddleware } from "http-proxy-middleware";

@Controller()
export class GatewayController {
  constructor(
    private readonly gatewayService: GatewayService,
    private readonly wsGateway: WsGateway,
    private readonly prisma: PrismaService,
    private readonly logService: LogService,
  ) {}

  @Get()
  getHello(): string {
    return "gateway-hello";
  }

  @MessagePattern(SysIntervalMsgType.GATEWAY_FE_EXCHANGE_EVENT)
  toFE(data: any) {
    const { toClientId = null, fromServerType, msg } = data;
    console.log(
      `gateway 收到发给前端的消息`,
      new Date().toISOString(),
      toClientId,
      fromServerType,
    );

    this.wsGateway.sendMsg({ toClientId, type: fromServerType, msg });
  }

  @Get("/initDb")
  @NoNeedLogin()
  async initDb(): Promise<string> {
    console.log("init mock db");
    const constantsRole = RBAC.roles.map((role) => {
      return {
        name: role,
      };
    });
    const constantsPermissions = RBAC.permissions.map((permission) => {
      return permission.name;
    });
    await this.prisma.role.createMany({
      data: constantsRole,
      skipDuplicates: true,
    });
    const roles = await this.prisma.role.findMany({
      where: {
        name: { in: RBAC.roles },
      },
    });
    let roleMap = new Map();
    let permissionMap = new Map();
    roles.forEach((role) => {
      roleMap.set(role.name, role.id);
    });

    await this.prisma.permission.createMany({
      data: RBAC.permissions,
      skipDuplicates: true,
    });
    const permissions = await this.prisma.permission.findMany({
      where: {
        name: {
          in: constantsPermissions,
        },
      },
    });
    permissions.forEach((permission) => {
      permissionMap.set(permission.name, permission.id);
    });
    let rolePermissionArr = [];
    for (const [role, permissions] of Object.entries(RBAC.rolePermissionMap)) {
      permissions.forEach((permission) => {
        rolePermissionArr.push({
          roleId: roleMap.get(role),
          permissionId: permissionMap.get(permission),
        });
      });
    }
    await this.prisma.rolePermission.createMany({
      data: rolePermissionArr,
      skipDuplicates: true,
    });

    await this.prisma.user.createMany({
      data: RBAC.user.map((user) => {
        return {
          username: user.username,
          password: user.password,
        };
      }),
      skipDuplicates: true,
    });
    const users = await this.prisma.user.findMany({
      where: {
        username: {
          in: RBAC.user.map((user) => user.username),
        },
      },
    });
    const userMap = new Map();
    RBAC.user.forEach((user) => {
      userMap.set(user.username, user.role);
    });
    let userRoleArr = [];
    users.forEach((user) => {
      const userId = user.id;
      const roleId = roleMap.get(userMap.get(user.username));
      userRoleArr.push({
        roleId,
        userId,
      });
    });
    await this.prisma.userRole.createMany({
      data: userRoleArr,
      skipDuplicates: true,
    });

    return "success";
  }


  @All('*')
  proxy(@Req() req: Request, @Res() res: Response) {
    const prefixSystem = req.url.split("/")[1];
    let targetPort;
    let rewritePath;
    switch (prefixSystem) {
      case configuration.systemServer.proxy_path:
        targetPort = configuration.systemServer.http_port
        rewritePath = configuration.systemServer.proxy_path
        break;
      case configuration.dicomServer.proxy_path:
        targetPort = configuration.dicomServer.http_port
        rewritePath = configuration.dicomServer.proxy_path
        break;
      case configuration.imageServer.proxy_path:
        targetPort = configuration.imageServer.http_port
        rewritePath = configuration.imageServer.proxy_path
        break;
    }
    console.log(targetPort, rewritePath);
    return createProxyMiddleware({
      target:`http://localhost:${targetPort}`, // 目标服务器
      pathRewrite: { [rewritePath]: "" },
      changeOrigin: true,
    })(req as any, res as any);
  }
}
